二级索引与一级索引
在mysql里面,我们默认用主键作为一级索引,因此只有一个。主键索引对应叶子节点指向的是整行数据。而其他我们自己建立的索引则统统都是2级索引,二级索引的叶子节点指向的则是主键。因此我们根据二级索引查询数据的时候是先根据索引查询到主键值,在回表根据聚簇索引查询整行数据。
B+树
我们为什么用B+树,是因为其树高度不高。我们根据索引查询的时候,没读到一个数据都是对树高度的遍历。每一次读取都是一次磁盘io,磁盘io效率太低,因此我们大多使用相对更加矮小的b+树。
重建索引
有时候数据量大了,因为索引的分页操作,导致其占了很多空间,因此要重建索引,来释放空间。
覆盖索引
覆盖索引,指的是那些不需要回表的索引。也就是只用走一个b+树。
因为我们要查询的内容已经在第一条二级索引里面获取到了。因此使用覆盖索引是个优化手段非常好的一个策略。
最左前缀原则
对于联合索引,(a,b,c),查询条件必须含有a才奏效,这就是最左匹配原则。还有字段模糊查询,必须是 “1%”之类的,前面的必须要有值。对于这种联合索引,a一样的,先按照b排序,再按照c排序。
mysql5.6之后的索引下推
在mysql 5.6之前,对于联合索引来说,在mysql5.6之前,mysql的联合索引中(a,b),在查询里面where a=”” and b=””;这类的sql我们的索引只能用到a这个字段来过滤,b是用不到的。
在mysql5.6以及之后的mysql对其做了优化,不只是用到了a,还用到了b,这个就是索引下推,从而大量减少了回表操作。
索引不准
在mysql里面,优化器会对sql进行分析,判断来选择使用什么索引,当我们使用 show index 会发现index的基数不对,这个统计是粗糙的,是其随机选出n个数据页,统计其不同值,得到一个平均值,然后乘以页数,得到其值,同时,当数据量更新超过一定值的时候,会再次触发统计。这个基数是来判断同样的扫描行数下,谁的基数大,那么就用谁做索引。有时候优化器会使用性能不好的索引,我们必须手动指定,挥着删除该索引等。索引不准的原因可能是。开启了一个事务,。没有关闭,然后又新开一个事务,删除大量数据,由于undolog可能导致判断基数时失效。
前缀索引
对于字符串字段来说,我们可以给一些超长的字段加前缀索引,从而减少索引文件的大小,比如邮箱,我们只需要比对前面的。缺点是,无法使用覆盖索引,索引区分度下降,查询次数变多。ps(为什么区分度很重要,前面说过了,你用一个索引查询的时候,如果都是一样的,那么每次都要遍历索引,在遍历表,效率比全表扫描还低)。举个例子,对于身份证号,我们如何建立索引呢,如果直接建立索引,但是身份证号太长了,如果建立索引,索引文件会非常大的。采用方案如下,在新建一个字段,给这个字段加个索引,这个字段的值是根据crc32()计算出来的值,当我们根据身份证号查询的时候,2个条件都加一下,这样就可以,索引文件小了很多,同时索引区分度也很高。很赞。
索引遇坑事件
1.使用索引字段函数
当你查询的数据列使用了函数,那么即使这个字段加了索引,那么依旧不适用索引。索引字段不能用函数,但是索引字段参数是可以用函数的,因此不是加了函数就不用索引了。
2.隐式转换
比如你这个sql的这个字段varchar类型加了索引,但是explain一下后,发现没有使用索引,为何呢。
这是因为在mysql里面,字符串和数字比较,是字符串转为为数字,因此当你索引字段是varchar,参数是int的时候,mysql优化器会默认给你的索引字段加CAST(tradid AS signed int) 进行转换,当然若是索引字段是int,参数是字符串,那么就不会存在问题。因为是参数在转换。
3.隐式字符转换
当2个表的字符集不同的时候,做表关联是用不上关联字段的索引的,很好理解,2个字符集不一样自然无法比较,那么就需要默认转换,这个转换和java的向上转型一样,都是向长度大的转型,因此有时候会对索引字段加函数操作,因此无法使用索引了。这个就要区分,谁被谁关联。我以前的文章说过,2个表2个字段都有索引,那么就是选择记录少的作为外表。记录多的走内表索引,因此,对于内表来说如果是被转换的,那么就无法走索引了,因为相当于对索引字段调用了函数。对此的优化方案,一。把字符类型修改。2数据量大,在参数那里就转换。
总结:索引字段不能使用函数,参数使用函数不影响sql.字符串转数字,utf8=utfmb4,